package com.bitcoin.scheduler.service;

import com.bitcoin.scheduler.domain.blockcc.KLineBlockCC;
import com.bitcoin.scheduler.websocket.client.ApiCallback;
import com.bitcoin.scheduler.websocket.client.gateio.GateIoApiClientFactory;
import com.bitcoin.scheduler.websocket.client.gateio.domain.KlineQueryResponse;
import com.bitcoin.scheduler.websocket.client.gateio.domain.KlineResult;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.mchange.lang.LongUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.jsoup.Jsoup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Closeable;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class MarketGateIoApiService {
    public final static String MARKET_NAME = "gate-io";

    private final static Map<String, Integer> symbols = Maps.newLinkedHashMap();

    static {
        symbols.put("BTC", 1);
        symbols.put("ETH", 2);
        symbols.put("XRP", 3);
        symbols.put("BNB", 22);
        symbols.put("EOS", 5);
        symbols.put("ETC", 17);
        symbols.put("NEO", 11);
        symbols.put("TRX", 9);
        symbols.put("XLM", 8);
        symbols.put("ADA", 6);
        symbols.put("LTC", 7);
        symbols.put("ONT", 31);
        symbols.put("IOTA", 10);
        symbols.put("QTUM", 18);
        symbols.put("AE", 27);
        symbols.put("BAT", 54);
        symbols.put("BCD", 39);
        symbols.put("BCX", 19);
        symbols.put("BOT", 374);
        symbols.put("BTG", 26);
        symbols.put("BTM", 32);
        symbols.put("BTO", 124);
        symbols.put("BTS", 34);
        symbols.put("CDT", 235);
        symbols.put("DCR", 49);
        symbols.put("DGD", 51);
        symbols.put("ELF", 55);
        symbols.put("FIL", 24);
        symbols.put("GNT", 60);
        symbols.put("GTC", 146);
        symbols.put("GXS", 90);
        symbols.put("HT", 138);
        symbols.put("IHT", 201);
        symbols.put("LINK", 103);
        symbols.put("LRC", 53);
        symbols.put("MANA", 104);
        symbols.put("MCO", 106);
        symbols.put("MKR", 44);
        symbols.put("NANO", 29);
        symbols.put("NAS", 66);
        symbols.put("PAY", 109);
        symbols.put("POWR", 100);
        symbols.put("RUFF", 141);
        symbols.put("SNT", 50);
        symbols.put("WAVES", 43);
        symbols.put("XVG", 25);
        symbols.put("ZEC", 28);
        symbols.put("ZIL", 41);
        symbols.put("ZRX", 46);
        symbols.put("ZSC", 372);
    }

    @Transactional
    public List<KLineBlockCC> getKlineResponse(String symbol, int days) throws IOException, InterruptedException {
        long startTime = System.currentTimeMillis();
        Date day = DateUtils.addDays(new Date(), -days);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(day);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        log.info("GateIo交易 {} 查询开始时间 {}", symbol, DateFormatUtils.format(calendar.getTime(), "yyyy/MM/dd HH:mm:ss"));
        long start = calendar.getTimeInMillis();
        calendar.setTime(DateUtils.addDays(calendar.getTime(), 3));
        calendar.set(Calendar.HOUR, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        log.info("GateIo交易 查询结束时间 {}", DateFormatUtils.format(calendar.getTime(), "yyyy/MM/dd HH:mm:ss"));
        long end = calendar.getTimeInMillis();
        List<KLineBlockCC> lineList = Lists.newArrayList();
        final int[] receive = {0};
       Closeable closeable =  GateIoApiClientFactory.newInstance().newWebSocketClient()
            .klineQuery(Math.toIntExact(start % 10000000),
                symbol + "_USDT",
                Math.toIntExact(start / 1000),
                Math.toIntExact(end / 1000),
                300, new ApiCallback<KlineQueryResponse>() {
                    @Override
                    public void onResponse(KlineQueryResponse response) {
                        for (KlineResult result : response.getResult()) {
                            KLineBlockCC line = new KLineBlockCC();
                            line.setBccId(symbols.get(symbol));
                            line.setCurrency("USDT");
                            line.setPriceTime(result.getTime());
                            line.setSymbol(symbol);
                            line.setMarket(MARKET_NAME);
                            line.setOpenPrice(result.getOpen());
                            line.setHighPrice(result.getHighest());
                            line.setLowPrice(result.getLowest());
                            line.setClosePrice(result.getClose());
                            line.setVolume(result.getVolume());
                            lineList.add(line);
                        }
                        receive[0] = 1;
                    }

                    @Override
                    public void onFailure(Throwable cause) {
                        cause.printStackTrace();
                        receive[0] = 1;
                    }
                }
            );
        while (receive[0] != 1) {
            if (System.currentTimeMillis() - startTime > 240 * 1000) {
                break;
            }
            Thread.sleep(1000);
        }
        closeable.close();
        return lineList;

    }
}
